import pulsectl
import time
from contextlib import contextmanager

class MixerControl:
    def __init__(self):
        self.pulse = pulsectl.Pulse('python-volume-control')

    def list_playing(self):
        res = []
        for sink in self.pulse.sink_input_list():
            app_name = sink.proplist.get('application.name')
            # print(sink.proplist)
            if app_name is not None:
                res.append(app_name)
        return res

    def any_playing(self):
        for app_name in self.list_playing():
            if not app_name.startswith('ALSA plug-in [python'):
                return True
        return False

    def __del__(self):
        self.pulse.close()

    @contextmanager
    def music_supressor(self, fade=0):
        sinks = self.pulse.sink_input_list()
        sinks = [sink for sink in sinks if sink.proplist.get('application.name') is not None and not sink.mute]
        if fade <= 0:
            try:
                for sink in sinks:
                    self.pulse.sink_input_mute(sink.index, 1)
                yield
            finally:
                for sink in sinks:
                    self.pulse.sink_input_mute(sink.index, 0)
        else:
            volumes = []
            for sink in sinks:
                volumes.append(sink.volume.values[0])
            try:
                for sink in sinks:
                    self.pulse.sink_input_mute(sink.index, 1)
                yield
            finally:
                d = 0.06
                n = max(1, round(fade / d + 1))
                for t in reversed(range(0, n + 1)):
                    scale = (0.01 ** (t / n)) ** 0.24
                    base = 0.01 ** 0.24
                    scale = (scale - base) / (1 - base)
                    time.sleep(d)
                    for i, sink in enumerate(sinks):
                        try:
                            self.pulse.volume_set_all_chans(sink, volumes[i] * scale)
                        except:
                            pass
                        if t == n:
                            self.pulse.sink_input_mute(sink.index, 0)

if __name__ == "__main__":
    mc = MixerControl()
    print(mc.list_playing())
    with mc.music_supressor(fade=1):
        print('Playing audio has been supressed...')
        time.sleep(1)
    print('Audio supression has been lifted...')
